package nimble.pay.trade.server.configuration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;
import java.time.Duration;
import java.util.HashSet;
import java.util.Set;

/**
 * @author max woods
 * @date 2018/8/6
 * 缓存配置
 */

@Configuration
@EnableCaching
public class CacheConfiguration extends CachingConfigurerSupport {

  /**
   * .
   * 默认缓存名称
   */
  private static final String CACHE_DEFAULT_NAME = "default";

  /**
   * 默认缓存时间（分钟）
   */
  private static final int CACHE_DEFAULT_EXPIRES = 30;

  /**
   * redis连接工厂
   */
  private final RedisConnectionFactory redisConnectionFactory;

  @Autowired
  public CacheConfiguration(final
                            RedisConnectionFactory redisConnectionFactory) {
    super();
    this.redisConnectionFactory = redisConnectionFactory;
  }

  @Bean
  @Override
  public KeyGenerator keyGenerator() {
    return (Object target, Method method, Object... params) -> {
      final StringBuilder stringBuilder = new StringBuilder();
      stringBuilder.append(target.getClass().getName());
      stringBuilder.append(method.getName());
      for (final Object obj : params) {
        stringBuilder.append(obj.toString());
      }
      return stringBuilder.toString();
    };
  }

  @Bean
  @Override
  public CacheManager cacheManager() {
    RedisCacheConfiguration cacheConfiguration =
        RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(CACHE_DEFAULT_EXPIRES))
            .disableCachingNullValues()
            .serializeKeysWith(RedisSerializationContext.
                SerializationPair.fromSerializer(new
                StringRedisSerializer()))
            .serializeValuesWith(RedisSerializationContext.
                SerializationPair.fromSerializer(new
                GenericJackson2JsonRedisSerializer()));
    final Set<String> cacheNames = new HashSet<>();
    cacheNames.add(CACHE_DEFAULT_NAME);
    return RedisCacheManager.builder(redisConnectionFactory).
        cacheDefaults(cacheConfiguration).initialCacheNames(cacheNames).build();
  }

  @Bean
  public RedisTemplate<String, String> redisTemplate() {
    final StringRedisTemplate template =
        new StringRedisTemplate(redisConnectionFactory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    template.afterPropertiesSet();
    return template;
  }
}
